UIPickView
UIPickView的属性:
picker的高度是固定的,如果设置大于216,就是216,如果小于216大于180,就是180;如果小于180大于162,就是162。
设置数据源及代理(UIPickerViewDelegate,UIPickerViewDataSource)
picker.dataSource=self;
picker.delegate=self;
- 创建
UIPickerView*picker=[[UIPickerView alloc]initWithFrame:CGRectMake(0, 50, 180, 300)];
picker.backgroundColor=[UIColor cyanColor];
[self.view addSubview:picker];
// 设置显示选中的指示条,默认为NO
picker.showsSelectionIndicator=YES;
// 设置数据源及代理
picker.dataSource=self;
picker.delegate=self;
UIPickView的常用方法:
// 刷新整个数据源
- (void)reloadAllComponents;
// 刷新选中列的数据
- (void)reloadComponent:(NSInteger)component;
// (用动画的效果)将指定的行滚动到中心
- (void)selectRow:(NSInteger)row inComponent:(NSInteger)component animated:(BOOL)animated;
// 返回选定的行
- (NSInteger)selectedRowInComponent:(NSInteger)component;
// 加载自定义pickView的行视图 ****
- (nullable UIView *)viewForRow:(NSInteger)row forComponent:(NSInteger)component;
UIPickView的数据源协议:
- 必须实现的协议方法:
// PickerView有多少列
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView;
// PickerView的每一列有多少行
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component;
UIPickView的代理协议:
//返回picker 有多少个区
-(NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
{
return 3;
}
//返回picker 每个区有多少行
-(NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component{
return 5;
}
// 如果同时实现返回字符串和view的方法,返回UIView的优先级比较高
- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(nullable UIView *)view __TVOS_PROHIBITED
{
// 返回自定义view
UIView *v = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 60, 60)];
v.backgroundColor = [UIColor redColor];
return v;
}
// NSAttributedString富文本属性: 可以描述文字大小和颜色(此方法不常用)
- (nullable NSAttributedString *)pickerView:(UIPickerView *)pickerView attributedTitleForRow:(NSInteger)row forComponent:(NSInteger)component;
// 返回pickerView的行标题
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
{
return @"xxxx";
}
// 选中第component第row的时候调用
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
}
例子
例一(自定义pickView中的view)
1、ViewController.m
#import "ViewController.h"
#import "FlageView.h"
#import "flag.h"
@interface ViewController ()<UIPickerViewDataSource,UIPickerViewDelegate>
@property (nonatomic,strong)UIPickerView * pickV;
@property (nonatomic,strong)NSMutableArray * flags;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
_pickV = [[UIPickerView alloc]initWithFrame:CGRectMake(0, 100,[UIScreen mainScreen].bounds.size.width, 250)];
//_pickV.backgroundColor = [UIColor redColor];
[self.view addSubview:_pickV];
_pickV.delegate = self;
_pickV.dataSource = self;
}
// 懒加载
-(NSMutableArray *)flags
{
if (_flags == nil) {
_flags = [NSMutableArray array];
NSString * filePath = [[NSBundle mainBundle]pathForResource:@"flags.plist" ofType:nil];
// 获取plist数据
NSMutableArray * array = [NSMutableArray arrayWithContentsOfFile:filePath];
// 字典数据转换成模型数据
/*
(实质就是将字典dic中的数据按照key赋值给flag数据模型)
如:
flag * flags = [[flag alloc]init];
flags.name = dic[@"name"];
flags.icon = dic[@"icon"];
*/
for (NSDictionary * dic in array) {
flag * flags = [flag flagWithDic:dic];
[_flags addObject:flags];
}
}
NSLog(@"%@",_flags);
return _flags;
}
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
{
return 1;
}
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
return self.flags.count;
}
- (CGFloat)pickerView:(UIPickerView *)pickerView rowHeightForComponent:(NSInteger)component
{
return 60;
}
- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view
{
FlageView * flagV = [[FlageView alloc]init];
// 取模型数据
flag * flg = _flags[row];
flagV.flag =flg;
return flagV;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
2、设置view的数据模型
#import <Foundation/Foundation.h>
@interface flag : NSObject
@property (nonatomic,copy)NSString * name;
@property (nonatomic,copy)NSString * icon;
+ (instancetype)flagWithDic:(NSDictionary *)dic;
@end
#import "flag.h"
@implementation flag
// 将字典中的数据转换成模型数据
+ (instancetype)flagWithDic:(NSDictionary *)dic
{
flag * flag = [[self alloc]init];
[flag setValuesForKeysWithDictionary:dic];
return flag;
}
@end
3、自定义view
#import <UIKit/UIKit.h>
#import "flag.h"
@interface FlageView : UIView
@property (nonatomic,strong)UILabel * label;
@property (nonatomic,strong)UIImageView * imageView;
@property (nonatomic,strong)flag * flag;
- (instancetype)initWithFrame:(CGRect)frame;
- (void)setFlag:(flag *)flag;
@end
#import "FlageView.h"
#define WIDTH [UIScreen mainScreen].bounds.size.width
@implementation FlageView
- (instancetype)initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame]) {
self.frame =CGRectMake(0, 0,WIDTH, 70);
self.label = [[UILabel alloc]initWithFrame:CGRectMake(0, 5, 100, 60)];
[self addSubview:self.label];
self.imageView = [[UIImageView alloc]initWithFrame:CGRectMake(WIDTH-100, 5, 100, 60)];
[self addSubview:self.imageView];
}
return self;
}
- (void)setFlag:(flag *)flag
{
self.label.text = flag.name;
self.imageView.image = [UIImage imageNamed:flag.icon];
}
@end
例二(生日选择器)
#import "ViewController.h"
@interface ViewController ()<UITextFieldDelegate>
@property (nonatomic,strong)UITextField * birthdayTF;
@property (nonatomic, weak) UIDatePicker *datePicker;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
_birthdayTF = [[UITextField alloc]initWithFrame:CGRectMake(100, 100, 100, 44)];
// 设置文本框的代码
_birthdayTF.delegate = self;
[self.view addSubview:_birthdayTF];
// 自定义生日键盘
[self setUpBirthdayKeyboard];
}
#pragma mark -自定义生日键盘
- (void)setUpBirthdayKeyboard
{
// 创建UIDatePicker
// 注意:UIDatePicker有默认的尺寸,可以不用设置frame
UIDatePicker *picker = [[UIDatePicker alloc] init];
_datePicker = picker;
// 设置地区 zh:中国
picker.locale = [NSLocale localeWithLocaleIdentifier:@"zh"];
// 设置日期的模式
picker.datePickerMode = UIDatePickerModeDate;
// 监听UIDatePicker的滚动
[picker addTarget:self action:@selector(dateChange:) forControlEvents:UIControlEventValueChanged];
_birthdayTF.inputView = picker;
}
// 当UIDatePicker滚动的时候调用
// 给生日文本框赋值
- (void)dateChange:(UIDatePicker *)datePicker
{
NSLog(@"%@",datePicker.date);
// 日期转换字符串
NSDateFormatter *fmt = [[NSDateFormatter alloc] init];
fmt.dateFormat = @"yyyy-MM-dd";
NSString *dateStr = [fmt stringFromDate:datePicker.date];
_birthdayTF.text = dateStr;
}
#pragma mark - UITextFieldDelegate
// 是否允许用户输入文字
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string{
return NO;
}
// 文本框开始编辑的时候调用
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
[self dateChange:_datePicker];
}
例三(城市选择器)
#import "ViewController.h"
@interface ViewController ()<UITextFieldDelegate,UIPickerViewDataSource,UIPickerViewDelegate>
@property (nonatomic,strong)UITextField * cityTF;
@property (nonatomic, weak) UIDatePicker *datePicker;
@property (nonatomic, strong) NSMutableArray *provinces;
@property (nonatomic, assign) NSInteger proIndex;// 记录下第0列选中的省份
@end
@implementation ViewController
// 懒加载省会
- (NSMutableArray *)provinces
{
if (_provinces == nil) {
// 装所有的省会
_provinces = [NSMutableArray array];
// 加载plist文件
NSString *filePath = [[NSBundle mainBundle] pathForResource:@"provinces.plist" ofType:nil];
NSArray *arr = [NSArray arrayWithContentsOfFile:filePath];
for (NSDictionary *dict in arr) {
// 字典转模型
XMGProvince *p = [XMGProvince provinceWithDict:dict];
[_provinces addObject:p];
}
}
return _provinces;
}
- (void)viewDidLoad {
[super viewDidLoad];
_cityTF = [[UITextField alloc]initWithFrame:CGRectMake(100, 100, 100, 44)];
// 设置文本框的代码
_cityTF.delegate = self;
[self.view addSubview:_cityTF];
// 自定义生日键盘
[self setUpCityKeyboard];
}
#pragma mark - UITextFieldDelegate
// 是否允许用户输入文字
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string{
return NO;
}
// 文本框开始编辑的时候调用
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
[self pickerView:_pickerView didSelectRow:0 inComponent:0];
}
#pragma mark - 自定义城市键盘
- (void)setUpCityKeyboard
{
UIPickerView *pickerView = [[UIPickerView alloc] init];
_pickerView = pickerView;
pickerView.dataSource = self;
pickerView.delegate = self;
_cityField.inputView = pickerView;
}
#pragma mark -UIPickerView
#pragma mark UIPickerView的数据源
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
{
return 2;
}
// pickerView的第0列描述省会,有多少个省
// pickerView的第1列描述选中的省会,有多少个城市
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
if (component == 0) { // 描述省会
return self.provinces.count;
}else{ // 描述选中的省会的城市
// 获取省会
XMGProvince *p = self.provinces[_proIndex];
return p.cities.count;
}
}
#pragma mark -UIPickerView的代理
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
{
if (component == 0) { // 描述省会
// 获取省会
XMGProvince *p = self.provinces[row];
return p.name;
}else{ // 描述选中的省会的城市
// 记录当前选中的省会
_proIndex = [pickerView selectedRowInComponent:0];
// 获取选中省会
XMGProvince *p = self.provinces[_proIndex];
#warning 如果不用_proIndex记录第0列选择的省,会导致在下面出现数组越界。
return p.cities[row];
}
}
// 全局断点就是帮我们定位到出bug的那一行。
// 滚动UIPickerView就会调用
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
if (component == 0)
{
// 滚动省会,刷新城市(1列)
[pickerView reloadComponent:1];
}
// 给城市文本框赋值
// 获取选中省会
XMGProvince *p = self.provinces[_proIndex];
// 获取选中的城市
NSInteger cityIndex = [pickerView selectedRowInComponent:1];
NSString *cityName = p.cities[cityIndex];
_cityTF.text = [NSString stringWithFormat:@"%@ %@",p.name,cityName];
}